package com.datang.litejvm.attribute;

import com.datang.litejvm.cmd.ByteCodeCommand;
import com.datang.litejvm.cmd.CommandParser;
import com.datang.litejvm.constant.ConstantPool;
import com.datang.litejvm.constant.ConstantUTF8Info;
import com.datang.litejvm.loader.ByteCodeIterator;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: 顶风少年
 * @Description: 代码
 * @date: 18:28 2022/6/12
 **/
public class CodeAttr extends AttributeInfo {
    private int maxStack;
    private int maxLocals;
    private int codeLen;
    private List<String> codes;
    private List<ByteCodeCommand> cmds;
    private int exceptionLen;//略
    private Object exceptionInfo;//略

    private LineNumberTable lineNumTable;
    private LocalVariableTable localVarTable;


    public CodeAttr(int attrNameIndex, String attrNameValue, int attrLen) {
        super(attrNameIndex, attrNameValue, attrLen);
    }

    public int getMaxStack() {
        return maxStack;
    }

    public void setMaxStack(int maxStack) {
        this.maxStack = maxStack;
    }

    public int getMaxLocals() {
        return maxLocals;
    }

    public void setMaxLocals(int maxLocals) {
        this.maxLocals = maxLocals;
    }

    public int getCodeLen() {
        return codeLen;
    }

    public void setCodeLen(int codeLen) {
        this.codeLen = codeLen;
    }

    public LineNumberTable getLineNumTable() {
        return lineNumTable;
    }

    public void setLineNumTable(LineNumberTable lineNumTable) {
        this.lineNumTable = lineNumTable;
    }

    public LocalVariableTable getLocalVarTable() {
        return localVarTable;
    }

    public void setLocalVarTable(LocalVariableTable localVarTable) {
        this.localVarTable = localVarTable;
    }

    public List<String> getCodes() {
        return codes;
    }

    public void setCodes(List<String> codes) {
        this.codes = codes;
    }

    public List<ByteCodeCommand> getCmds() {
        return cmds;
    }

    public void setCmds(List<ByteCodeCommand> cmds) {
        this.cmds = cmds;
    }

    public void parse(ByteCodeIterator iter, ConstantPool pool) {
        //栈深度
        int maxStack = iter.nextU2ToInt();
        this.setMaxStack(maxStack);
        //局部变量表个数
        int maxLocals = iter.nextU2ToInt();
        this.setMaxLocals(maxLocals);
        //代码长度
        int codeLen = iter.nextU4ToInt();
        this.setCodeLen(codeLen);
        //指令表
        List<String> codes = new ArrayList<>();
        for (int x = 0; x < codeLen; x++) {
            String code = iter.nextUxToHexString(1);
            codes.add(code);
        }
        this.setCodes(codes);
        //将字节码指令分组
        this.cmds = CommandParser.parse(codes,pool);

        int exceptionLen = iter.nextU2ToInt();//todo 异常 略
        iter.nextUxToHexString(exceptionLen);//todo 异常 略
        //子属性 LineNumberTable和 LocalVariableTable
        int childAttr = iter.nextU2ToInt();
        for (int i = 0; i < childAttr; i++) {
            //LineNumberTable
            int attributeNameIndex = iter.nextU2ToInt();
            ConstantUTF8Info nameInfo = (ConstantUTF8Info) pool.getConstantInfo(attributeNameIndex);
            String nameValue = nameInfo.getBytes();
            //属性长度
            int attributeLength = iter.nextU4ToInt();
            if (nameValue.equals(AttributeInfo.LINE_NUMBER_TABLE)) {
                LineNumberTable lineNumberTable = new LineNumberTable(attributeNameIndex, nameValue, attributeLength);
                lineNumberTable.parse(iter, pool);
                this.setLineNumTable(lineNumberTable);
            } else if (nameValue.equals(AttributeInfo.LOCAL_VARIABLE_TABLE)) {
                LocalVariableTable localVariableTable = new LocalVariableTable(attributeNameIndex, nameValue, attributeLength);
                localVariableTable.parse(iter, pool);
                this.setLocalVarTable(localVariableTable);
            }else if (nameValue.equals(AttributeInfo.STACK_MAP_TABLE)){
                StackMapTable stackMapTable = new StackMapTable(attributeNameIndex, nameValue, attributeLength);
                stackMapTable.parse(iter, pool);
            }
        }
    }
}
